#include "CommaHandler.h"
#include "..\..\Common\StringHelper.h"
#include "..\..\Common\AssertHelper.h"

using namespace std;

namespace CExpression
{
	bool CommaHandler::ParseCore(ParseContext &context)
	{
		bool ret = false;
		shared_ptr<ExpressionToken> token=context.Tokens()[context.CurrentTokenIndex()];
		if (token->Token == TEXT(","))
        {
			ret = true;
            if(this->CheckComma(token,context))
			{
				if (context.OperatorStack().size() > 0)
				{
					this->ParseComma(token,context);
				}
				else
				{
					context.SetError();
					context.SetErrorMsg(TEXT("Missing operand before comma."));
				}
			}
        }
        return ret;
	}

	void CommaHandler::ParseComma(shared_ptr<ExpressionToken> token,ParseContext &context)
	{
		shared_ptr<ExpressionToken> op=context.OperatorStack().top();
		context.OperatorStack().pop();
		while(!StringHelper::EndWith(op->Token,TEXT("(")))
		{
			if(AssertHelper::CreateHandlerExists(op->Token,context,TEXT("Unknow operator.")))
			{
				map<ExpressionString,ParseContext::CreateNodeHandlerPtr>::iterator createHandlerIter=ParseContext::createHandlerMap->find(op->Token);
				createHandlerIter->second(context);
				if(context.OperatorStack().size()>0)
				{
					op=context.OperatorStack().top();
					context.OperatorStack().pop();
				}
				else
				{
					context.SetError();
					context.SetErrorMsg(TEXT("Missing operand before comma."));
					return;
				}
			}
			else
			{
				return;
			}
		}
		context.OperatorStack().push(op);
	}

	bool CommaHandler::CheckComma(shared_ptr<ExpressionToken> token,ParseContext &context)
	{
		bool ret=true;
		if(context.CurrentTokenIndex()!=context.Tokens().size()-1)
		{
			shared_ptr<ExpressionToken> nextToken=context.Tokens()[context.CurrentTokenIndex()+1];
			ExpressionChar nextChar=nextToken->Token[nextToken->Token.size()-1];
			if(StringHelper::IsUnitaryOperatorChar(nextChar)||nextChar==TEXT(',')||nextChar==TEXT(')'))
			{
				context.SetError();
				context.SetErrorMsg(TEXT("Missing operand after comma."));
				ret=false;
			}
		}
		else
		{
			context.SetError();
			context.SetErrorMsg(TEXT("Missing operand after comma."));
			ret=false;
		}
		return ret;
	}
}